<template>
  <div class="container">
    <h1>{{ msg }}</h1>
    <h1>{{ this.roomStatusMessage }}</h1>
    <div class="tools">
      <button
        @click="jsjointrigger"
        :class="{ active: isJoined, inactive: !isJoined }"
      >
        {{ joinButtonMessage }}
      </button>
      <button
        @click="jssendaudio"
        :class="{ active: isSendingAudio, inactive: !isSendingAudio }"
      >
        {{ audioButtonMessage }}
      </button>
      <button
        @click="jssendvideo"
        :class="{ active: isSendingVideo, inactive: !isSendingVideo }"
      >
        {{ videoButtonMessage }}
      </button>
    </div>

    <h3 class="heading">Local</h3>
    <div class="local-tracks" id="localTracks" ref="localTracks"></div>
    <h3 class="heading">Remote</h3>
    <div class="remote-tracks" id="remoteTracks" ref="remoteTracks"></div>
  </div>
</template>

<script>
import Room from "../lib/room";

export default {
  name: "MainLayout",
  props: {
    msg: String,
  },
  data: function () {
    return {
      isJoined: false,
      roomStatusMessage: "You are not in a room, click on join to enter a room",
      isInRoom: false,
      isSendingVideo: false,
      isSendingAudio: false,
      room: null,
      joinButtonMessage: "Join Room",
      videoButtonMessage: "Share Video",
      audioButtonMessage: "Share Audio",
    };
  },
  mounted: function () {
    // 创建 Room 实例
    this.room = window.room = new Room();
    // 监听 peerJoined 事件
    this.room.on("@peerJoined", ({ peerId }) => {
      console.log("new peer joined", peerId);
    });
    // 监听 peerClosed 事件
    this.room.on("@peerClosed", ({ peerId }) => {
      this.removeMediaEl(this.$refs.remoteTracks, "data-peer-id", peerId);
    });
    // 监听 consumer 事件
    this.room.on("@consumer", async (consumer) => {
      const {
        id,
        appData: { peerId },
        track,
      } = consumer;
      console.log("receive consumer", consumer);
      const el = this.createMediaEl(track, peerId, id);
      this.$refs.remoteTracks.append(el);
    });
    // 监听 consumerClosed 事件
    this.room.on("@consumerClosed", ({ consumerId }) => {
      this.removeMediaEl(this.$refs.remoteTracks, "data-search-id", consumerId);
    });
    // 监听 producerClosed 事件
    this.room.on("@producerClosed", ({ producerId }) => {
      this.removeMediaEl(this.$refs.localTracks, "data-search-id", producerId);
    });
  },

  methods: {
    // 加入房间
    async jsjointrigger() {
      // 确保未加入房间 ...
      if (!this.isInRoom) {
        // 加入房间 ...
        this.room.join();
        // 监听 open 事件
        this.room.once("@open", ({ peers }) => {
          console.log(`${peers.length} peers in this room.`);
          this.isInRoom = true; // 标记加入
        });
        this.roomStatusMessage = "";
        this.isJoined = true; // 标记加入
        this.joinButtonMessage = "In a room";
      }
    },
    // 发送音频
    async jssendaudio() {
      // 确保未加入房间, 确保未发送音频 ...
      if (this.isInRoom && !this.isSendingAudio) {
        // 会提示用户给予使用媒体输入的许可，媒体输入会产生一个MediaStream，里面包含了请求的媒体类型的轨道。
        // 此流可以包含一个视频轨道（来自硬件或者虚拟视频源，比如相机、视频采集设备和屏幕共享服务等等）
        // 此流可以包含一个音频轨道（同样来自硬件或虚拟音频源，比如麦克风、A/D转换器等等），也可能是其它轨道类型。
        const stream = await navigator.mediaDevices.getUserMedia({
          audio: true,
        });
        // 从音频流中获取音频轨道
        const audioTrack = stream.getAudioTracks()[0];
        // 发送音频 ...
        const producer = await this.room.sendAudio(audioTrack);
        console.log("beepboop:" + audioTrack);
        // 插入 Media Element
        this.$refs.localTracks.append(
          this.createMediaEl(audioTrack, "", producer.id)
        );
        // 标记发送音频
        this.isSendingAudio = true;
        this.audioButtonMessage = "Sharing Audio";
      }
    },
    // 发送视频
    async jssendvideo() {
      // 确保未加入房间, 确保未发送视频 ...
      if (this.isInRoom && !this.isSendingVideo) {
        // 会提示用户给予使用媒体输入的许可，媒体输入会产生一个MediaStream，里面包含了请求的媒体类型的轨道。
        // 此流可以包含一个视频轨道（来自硬件或者虚拟视频源，比如相机、视频采集设备和屏幕共享服务等等）
        // 此流可以包含一个音频轨道（同样来自硬件或虚拟音频源，比如麦克风、A/D转换器等等），也可能是其它轨道类型。
        const stream = await navigator.mediaDevices.getUserMedia({
          video: true,
        });
        // 从视频流中获取视频轨道
        const videoTrack = stream.getVideoTracks()[0];
        // 发送视频 ...
        const producer = await this.room.sendVideo(videoTrack);
        // 插入 Media Element
        this.$refs.localTracks.append(
          this.createMediaEl(videoTrack, "", producer.id)
        );
        // 标记发送视频
        this.isSendingVideo = true;
        this.videoButtonMessage = "Sharing Video";
      }
    },
    // 创建 Media Element
    createMediaEl(track, peerId, searchId) {
      const el = document.createElement(track.kind);
      el.srcObject = new MediaStream([track]);
      el.setAttribute("data-peer-id", peerId);
      el.setAttribute("data-search-id", searchId);
      el.playsInline = true;
      el.play().catch(console.error);
      el.height = 288;
      el.width = 512;
      return el;
    },
    // 移除 Media Element
    removeMediaEl($container, key, id) {
      Array.from($container.children)
        .filter((el) => el.getAttribute(key) === id)
        .forEach((el) => {
          el.srcObject.getTracks().forEach((track) => track.stop());
          el.remove();
        });
    },
  },
};
</script>

<style scoped>
button {
  color: white;
  height: 3em;
  width: 10em;
  margin: 1em;
  font-size: 18px;
}

button.active {
  background-color: green;
}

button.inactive {
  background-color: red;
}
</style>
